package com.tech.platform.cms.authz.sso.service;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tech.platform.cms.authz.common.model.LoginUserModel;
import com.tech.platform.cms.authz.common.utils.JwtUtils;
import com.tech.platform.cms.authz.sso.config.SsoYmlConfig;
import com.tech.platform.cms.authz.sso.dao.bean.SubSystem;
import com.tech.platform.cms.authz.sso.dao.bean.Tenant;
import com.tech.platform.cms.authz.sso.dao.mapper.SubSystemMapper;
import com.tech.platform.cms.authz.sso.exception.NoSuchClientException;
import com.tech.platform.cms.authz.sso.exception.NoSuchHgcTokenException;
import com.tech.platform.cms.authz.sso.exception.NoSuchHgtTokenException;
import com.tech.platform.cms.authz.sso.utils.JwtRedisUtils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.security.auth.spi.LoginModule;

@Service
@Slf4j
public class JwtTokenService {

    @Autowired
    private SsoYmlConfig ssoYmlConfig;

    @Autowired
    private SubSystemMapper SubSystemMapper;

    @Autowired
    private JwtRedisUtils jwtRedisUtils;

    @Cacheable(value = "ssoClientSecretKey",key = "#clientId")
    public String getClientSecretKey(String clientId) throws NoSuchClientException {
        QueryWrapper<SubSystem> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("system_id",clientId);
        queryWrapper.eq("status",1);
        SubSystem client = SubSystemMapper.selectOne(queryWrapper);
        if(client==null){
            throw new NoSuchClientException();
        }
        return client.getSecretKey();
    }

    public String getHgcSecretKey(){
        return ssoYmlConfig.getHgcJwtSecretKey();
    }

    public boolean checkHgtToken(String token,String clientId) throws JwtException {
        return JwtUtils.checkToken(token,getClientSecretKey(clientId));
    }

    public boolean isHgtTokenExpired(String token,String clientId) throws JwtException{
        return JwtUtils.isTokenExpired(token,getClientSecretKey(clientId));
    }

    public boolean checkHgcToken(String token){
        return JwtUtils.checkToken(token,getHgcSecretKey());
    }

    public boolean isHgcTokenExpire(String token){
        return JwtUtils.isTokenExpired(token,getHgcSecretKey());
    }

    public String generatorHgtToken(String clientId,LoginUserModel loginUserModel){
        String token = JwtUtils.generatorToken(loginUserModel.getUserId()+"",JSONUtil.toJsonStr(loginUserModel),getClientSecretKey(clientId));
        jwtRedisUtils.saveHgtToken(clientId,loginUserModel.getUserId(),token);
        return token;
    }

    public String generatorHgcToken(LoginUserModel loginUserModel){
        String token = JwtUtils.generatorToken(loginUserModel.getUserId()+"",JSONUtil.toJsonStr(loginUserModel),getHgcSecretKey());
        jwtRedisUtils.saveHgcToken(loginUserModel.getUserId(),token);
        return token;
    }

    public boolean checkHgcToken(String clientId,String hgtToken){
        Claims claims = JwtUtils.getClaims(hgtToken,getClientSecretKey(clientId));
        String subject = claims.getSubject();
        LoginUserModel loginUserModel = JSONUtil.toBean(subject, LoginUserModel.class);
        String redisSaveToken = jwtRedisUtils.getHgtToken(clientId,loginUserModel.getUserId());
        if(StrUtil.isBlank(redisSaveToken)){
            return false;
        }

        if(redisSaveToken.equals(hgtToken)){
            return true;
        }

        return false;
    }

    public LoginUserModel getLoginUserModel(String clientId,String token) throws NoSuchHgtTokenException {
        Claims claims = JwtUtils.getClaims(token,getClientSecretKey(clientId));
        String subject = claims.getSubject();
        LoginUserModel loginUserModel = JSONUtil.toBean(subject, LoginUserModel.class);
        if(ObjectUtil.isNull(loginUserModel)){
            throw new NoSuchHgtTokenException();
        }

        return loginUserModel;
    }

    public LoginUserModel getLoginUserModel(String token) throws NoSuchHgcTokenException{
        Claims claims = JwtUtils.getClaims(token,getHgcSecretKey());
        String subject = claims.getSubject();
        LoginUserModel loginUserModel = JSONUtil.toBean(subject, LoginUserModel.class);
        if(ObjectUtil.isNull(loginUserModel)){
            throw new NoSuchHgcTokenException();
        }

        return loginUserModel;
    }

    private boolean checkHgcToken(int userId,String token){
        String redisSaveToken = jwtRedisUtils.getHgcToken(userId);
        if(StrUtil.isBlank(redisSaveToken)){
            return false;
        }

        if(redisSaveToken.equals(token)){
            return true;
        }

        return false;
    }
}
